;/////////////////////////////////////////////////////////////;
;                                                             ;
;                  SimpleDX11 Mesh Procedures                 ;
;                                                             ;
;                                                             ;
;                   (c) 2013 SimpleDX Team                    ;
;                                                             ;
;                         License: MIT                        ;
;                                                             ;
;/////////////////////////////////////////////////////////////;


;-//    Private structures    //
Structure Mesh_Template 
  *vTable
  *p.Mesh
  
  *SD3D.Screen3D
  *Device.ID3D11Device
  *ImmediateContext.ID3D11DeviceContext
  
  *VBuffer.ID3D11Buffer
  *IBuffer.ID3D11Buffer
  
  Stride.l
  Topology.l  
  
  *VertexArray
  *IntexArray
  
  IndexCount.l
  
  Offset.l
  
EndStructure

;-//    Constructor    //
Procedure New_Mesh(*SD3D.Screen3D, Flags.l= #Null)
  Protected *this.Mesh_Template
 
  *this = AllocateMemory(SizeOf(Mesh_Template))
  InitializeStructure(*this, Mesh_Template)
  
  If *this
    *this\vTable = ?Mesh_Class    
    *this\p = *this       
    
    *this\SD3D              = *SD3D
    *this\Device            = *SD3D\GetDevice()
    *this\ImmediateContext  = *SD3D\GetDeviceContext()  
    *this\Stride            = SizeOf(XMFLOAT4)
    *this\Topology          = #D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
    
    *this\Offset            = #Null
        
    ProcedureReturn *this
  EndIf  
  ProcedureReturn #False
EndProcedure

Procedure Mesh_GetTopology(*this.Mesh_Template)
  ProcedureReturn *this\Topology 
EndProcedure

Procedure Mesh_SetTopology(*this.Mesh_Template, Topology.l)
  *this\Topology = Topology
EndProcedure


Procedure Mesh_GetStride(*this.Mesh_Template)
  ProcedureReturn *this\Stride 
EndProcedure

Procedure Mesh_SetStride(*this.Mesh_Template, Stride.l)
   *this\Stride = Stride
EndProcedure

Procedure Mesh_SetOffset(*this.Mesh_Template, Offset.l)
  *this\Offset = Offset 
  ProcedureReturn *this\Offset 
EndProcedure

Procedure Mesh_GetOffset(*this.Mesh_Template)
  ProcedureReturn *this\Offset 
EndProcedure

Procedure Mesh_GetVBuffer(*this.Mesh_Template)
  ProcedureReturn *this\VBuffer 
EndProcedure

Procedure Mesh_GetIBuffer(*this.Mesh_Template)
  ProcedureReturn *this\IBuffer 
EndProcedure


Procedure Mesh_CreateBuffer(*this.Mesh_Template, *VertexArray, *IntexArray)
  
  If *this\VBuffer : *this\VBuffer\Release() : EndIf    
  
  *this\VertexArray = *VertexArray
  *this\IntexArray  = *IntexArray
  
  Protected Result.l = #S_OK
  
  
  Protected vBufferDesc.D3D11_BUFFER_DESC
  Protected VSD.D3D11_SUBRESOURCE_DATA

  vBufferDesc\Usage          = #D3D11_USAGE_DEFAULT
  vBufferDesc\ByteWidth      = MemorySize(*VertexArray)
  vBufferDesc\BindFlags      = #D3D11_BIND_VERTEX_BUFFER
  vBufferDesc\CPUAccessFlags = #Null
    

  VSD\pSysMem = *VertexArray
  
  Result = *this\Device\CreateBuffer(vBufferDesc, VSD, @*this\VBuffer) 
  If Result
    ProcedureReturn Result
  EndIf  
  

  If *this\IBuffer : *this\IBuffer\Release() : EndIf
  
  
  Protected IndexBufferDesc.D3D11_BUFFER_DESC
  IndexBufferDesc\Usage           = #D3D11_USAGE_DEFAULT
  IndexBufferDesc\ByteWidth       = MemorySize(*IntexArray)    
  IndexBufferDesc\BindFlags       = #D3D11_BIND_INDEX_BUFFER
  IndexBufferDesc\CPUAccessFlags  = #Null
  
  Protected ISD.D3D11_SUBRESOURCE_DATA
  ISD\pSysMem = *IntexArray
  
  Result = *this\Device\CreateBuffer(IndexBufferDesc, ISD, @*this\IBuffer)
  If Result
    ProcedureReturn Result
  EndIf
  
  *this\IndexCount = MemorySize(*IntexArray) / SizeOf(Long)
  
  
  ProcedureReturn Result
EndProcedure


Procedure Mesh_Render(*this.Mesh_Template)
  
  *this\ImmediateContext\IASetVertexBuffers(0, 1, @*this\VBuffer, @*this\Stride, @*this\Offset)
  *this\ImmediateContext\IASetIndexBuffer(*this\IBuffer, #DXGI_FORMAT_R32_UINT, 0)
  *this\ImmediateContext\IASetPrimitiveTopology(*this\Topology)

  *this\ImmediateContext\DrawIndexed(*this\IndexCount, 0, 0)   

EndProcedure

Procedure Mesh_Release(*this.Mesh_Template)
  
  If *this\VBuffer : *this\VBuffer\Release() : EndIf 
  If *this\IBuffer : *this\IBuffer\Release() : EndIf 
 
  FreeMemory(*this)
EndProcedure

;-//    Private procedures    //



;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
;-//    DataSection    //
DataSection
  Mesh_Class:    
  Data.i @Mesh_GetTopology()
  Data.i @Mesh_SetTopology()
  Data.i @Mesh_GetStride()
  Data.i @Mesh_SetStride()
  Data.i @Mesh_GetVBuffer()
  Data.i @Mesh_GetIBuffer()
  Data.i @Mesh_CreateBuffer()
  Data.i @Mesh_Render()
  Data.i @Mesh_Release()   
EndDataSection









; IDE Options = PureBasic 5.20 beta 14 LTS (Windows - x64)
; CursorPosition = 183
; FirstLine = 136
; Folding = ---
; EnableXP
; EnableCompileCount = 0
; EnableBuildCount = 0